// Copyright (c) 2022 Presto Labs Pte. Ltd.
// Author: lucasyoo

#pragma once

#include <numeric>

#include "coin2/strategy/order_executor/layering_executor.h"

namespace coin2::strategy::order_executor {

using IOrderSubsystem = exchange::base::order::IOrderSubsystem;
using coin2::exchange::base::symbology::IProductInfo;
using OrderContext = coin2::exchange::base::order::OrderContext;
using OrderList = std::vector<const OrderContext*>;
using LayeringExecutor = coin2::strategy::order_executor::LayeringExecutor;
using LayeringLevels = coin2::strategy::order_executor::LayeringLevels;


class LayeringExecutor2 : public LayeringExecutor {
 public:
  LayeringExecutor2(
      const PassiveExecutorConfig& config,
      IOrderSubsystem* os,
      std::optional<int64_t> timestamp,
      const TopBook* book,
      GetProductHolderFunc get_product_holder,
      std::optional<double> lot_size_quote = std::nullopt,
      const bool verbose = false);

  std::vector<LayeringLevels::Level> GetMostDesiredModification(
      LayeringLevels layering_levels,
      int64_t timestamp,
      int sign,
      const OrderList& wo_list,
      LayeringExecutor2* layering_executor);

  void ManageSideOrders(int64_t timestamp, int sign, LayeringLevels levels);

  void ManageRisk(int64_t timestamp);

  int GetBuyWorkingOrderCount();
  int GetSellWorkingOrderCount();
  std::vector<int64_t> GetAllOrderIds();
  std::vector<std::pair<double, double>> GetBuyWorkingOrderPairs();
  std::vector<std::pair<double, double>> GetSellWorkingOrderPairs();

  IOrderSubsystem* os() const { return os_; }
 private:
  std::map<std::pair<int, LayeringLevels::OperationType>, int64_t> prev_oper_ts_;
  int64_t prev_buy_cancel_ts_{0L};
  int64_t prev_sell_cancel_ts_{0L};
};

}